{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}

--------------------------------------------------------------------------------

module Cardano.Benchmarking.Profile.Genesis (
  Epoch (..), epochTimeline
, plutusV1CostNames, plutusV2CostNames, plutusV3CostNames
) where

--------------------------------------------------------------------------------

import           Prelude
import           Data.String (fromString)
import           GHC.Generics
-- Package: aeson.
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.KeyMap as KeyMap
-- Package: containers.
import qualified Data.Map as Map
-- Package: self.
import qualified Paths_cardano_profile as Paths

--------------------------------------------------------------------------------

data Epoch = Epoch
  { shelley :: Maybe (KeyMap.KeyMap Aeson.Value)
  , alonzo :: Maybe (KeyMap.KeyMap Aeson.Value)
  , conway :: Maybe (KeyMap.KeyMap Aeson.Value)
  }
  deriving (Eq, Show, Generic)

instance Semigroup Epoch where
  (<>) e1 e2 =
    Epoch {
      shelley = shelley e1 `union` shelley e2
    , alonzo  = alonzo  e1 `union` alonzo  e2
    , conway  = conway  e1 `union` conway  e2
    }

instance Monoid Epoch where
  mempty = Epoch mempty mempty mempty -- Start with an empty "epoch zero"!
  mappend = (<>)

instance Aeson.FromJSON Epoch

instance Aeson.ToJSON Epoch

--------------------------------------------------------------------------------

epochTimeline :: Integer -> IO Epoch
epochTimeline upToEpochNumber = do
  e <-epochTimeline' upToEpochNumber
  return $ e {
      -- The "shelley" object in "epoch-timeline.json" entries is directly the
      -- "protocolParams" object used in the node's "shelley-genesis.json".
      shelley =
        case shelley e of
          Nothing -> Nothing
          (Just s) -> Just $ KeyMap.fromList [
                        ("protocolParams", Aeson.Object s)
                      ]
    -- If "plutusV3CostModel" is a JSON object like "PlutusV1" and "PlutusV2"
    -- convert it to an array with just the values (numbers).
    , conway =
       case conway e of
         Nothing -> Nothing
         (Just c) ->
           Just $ KeyMap.mapWithKey
             (\k v ->
               if k == "plutusV3CostModel"
               then case v of
                      (Aeson.Object costModel) -> Aeson.Array $ foldl
                        (\acc name ->
                          case KeyMap.lookup (fromString name) costModel of
                            (Just int) -> acc <> return int
                            Nothing -> error $ "No Plutus V3 Cost Model with name \"" ++ name ++ "\" "
                        )
                        mempty
                        (take (KeyMap.size costModel) plutusV3CostNames)
                      _ -> v
               else v
             )
             c
  }

-- Collects all properties from epochs lower or equal than the desired one.
epochTimeline' :: Integer -> IO Epoch
epochTimeline' upToEpochNumber = do
  fp <- Paths.getDataFileName "data/genesis/epoch-timeline.json"
  -- Get the epochs sorted by number.
  -- The key is a string, so we need to use the "epoch" numeric property.
  eitherValue <- (Aeson.eitherDecodeFileStrict fp :: IO (Either String (Map.Map Integer Epoch)))
  return $ case eitherValue of
    -- If a proper JSON object, collect!
    (Right epochs) -> Map.foldlWithKey'
      (\acc key epochEntry ->
        if key <= upToEpochNumber
        then acc <> epochEntry
        else acc
      )
      mempty
      epochs
    (Left e) -> error $ "\"data/genesis/epoch-timeline.json\": " ++ e

union :: Maybe (KeyMap.KeyMap Aeson.Value)
      -> Maybe (KeyMap.KeyMap Aeson.Value)
      -> Maybe (KeyMap.KeyMap Aeson.Value)
union Nothing Nothing = Nothing
union Nothing (Just a) = Just a
union (Just a) Nothing = Just a
union (Just a) (Just b) = Just $ KeyMap.unionWithKey unionWithKey a b

-- Right-biased merge of both JSON objects at all depths.
unionWithKey :: KeyMap.Key -> Aeson.Value -> Aeson.Value -> Aeson.Value
-- Recurse if it's an object.
unionWithKey _ (Aeson.Object a) (Aeson.Object b) =
  Aeson.Object $ KeyMap.unionWithKey unionWithKey a b
-- If not an object prefer the right value.
unionWithKey _ _ b = b

-- The cost models cost names, the order is important for Plutus V3.
--------------------------------------------------------------------------------

plutusV1CostNames :: [String]
plutusV1CostNames =
  [
    "addInteger-cpu-arguments-intercept"
  , "addInteger-cpu-arguments-slope"
  , "addInteger-memory-arguments-intercept"
  , "addInteger-memory-arguments-slope"
  , "appendByteString-cpu-arguments-intercept"
  , "appendByteString-cpu-arguments-slope"
  , "appendByteString-memory-arguments-intercept"
  , "appendByteString-memory-arguments-slope"
  , "appendString-cpu-arguments-intercept"
  , "appendString-cpu-arguments-slope"
  , "appendString-memory-arguments-intercept"
  , "appendString-memory-arguments-slope"
  , "bData-cpu-arguments"
  , "bData-memory-arguments"
  , "blake2b-cpu-arguments-intercept"
  , "blake2b-cpu-arguments-slope"
  , "blake2b-memory-arguments"
  , "cekApplyCost-exBudgetCPU"
  , "cekApplyCost-exBudgetMemory"
  , "cekBuiltinCost-exBudgetCPU"
  , "cekBuiltinCost-exBudgetMemory"
  , "cekConstCost-exBudgetCPU"
  , "cekConstCost-exBudgetMemory"
  , "cekDelayCost-exBudgetCPU"
  , "cekDelayCost-exBudgetMemory"
  , "cekForceCost-exBudgetCPU"
  , "cekForceCost-exBudgetMemory"
  , "cekLamCost-exBudgetCPU"
  , "cekLamCost-exBudgetMemory"
  , "cekStartupCost-exBudgetCPU"
  , "cekStartupCost-exBudgetMemory"
  , "cekVarCost-exBudgetCPU"
  , "cekVarCost-exBudgetMemory"
  , "chooseData-cpu-arguments"
  , "chooseData-memory-arguments"
  , "chooseList-cpu-arguments"
  , "chooseList-memory-arguments"
  , "chooseUnit-cpu-arguments"
  , "chooseUnit-memory-arguments"
  , "consByteString-cpu-arguments-intercept"
  , "consByteString-cpu-arguments-slope"
  , "consByteString-memory-arguments-intercept"
  , "consByteString-memory-arguments-slope"
  , "constrData-cpu-arguments"
  , "constrData-memory-arguments"
  , "decodeUtf8-cpu-arguments-intercept"
  , "decodeUtf8-cpu-arguments-slope"
  , "decodeUtf8-memory-arguments-intercept"
  , "decodeUtf8-memory-arguments-slope"
  , "divideInteger-cpu-arguments-constant"
  , "divideInteger-cpu-arguments-model-arguments-intercept"
  , "divideInteger-cpu-arguments-model-arguments-slope"
  , "divideInteger-memory-arguments-intercept"
  , "divideInteger-memory-arguments-minimum"
  , "divideInteger-memory-arguments-slope"
  , "encodeUtf8-cpu-arguments-intercept"
  , "encodeUtf8-cpu-arguments-slope"
  , "encodeUtf8-memory-arguments-intercept"
  , "encodeUtf8-memory-arguments-slope"
  , "equalsByteString-cpu-arguments-constant"
  , "equalsByteString-cpu-arguments-intercept"
  , "equalsByteString-cpu-arguments-slope"
  , "equalsByteString-memory-arguments"
  , "equalsData-cpu-arguments-intercept"
  , "equalsData-cpu-arguments-slope"
  , "equalsData-memory-arguments"
  , "equalsInteger-cpu-arguments-intercept"
  , "equalsInteger-cpu-arguments-slope"
  , "equalsInteger-memory-arguments"
  , "equalsString-cpu-arguments-constant"
  , "equalsString-cpu-arguments-intercept"
  , "equalsString-cpu-arguments-slope"
  , "equalsString-memory-arguments"
  , "fstPair-cpu-arguments"
  , "fstPair-memory-arguments"
  , "headList-cpu-arguments"
  , "headList-memory-arguments"
  , "iData-cpu-arguments"
  , "iData-memory-arguments"
  , "ifThenElse-cpu-arguments"
  , "ifThenElse-memory-arguments"
  , "indexByteString-cpu-arguments"
  , "indexByteString-memory-arguments"
  , "lengthOfByteString-cpu-arguments"
  , "lengthOfByteString-memory-arguments"
  , "lessThanByteString-cpu-arguments-intercept"
  , "lessThanByteString-cpu-arguments-slope"
  , "lessThanByteString-memory-arguments"
  , "lessThanEqualsByteString-cpu-arguments-intercept"
  , "lessThanEqualsByteString-cpu-arguments-slope"
  , "lessThanEqualsByteString-memory-arguments"
  , "lessThanEqualsInteger-cpu-arguments-intercept"
  , "lessThanEqualsInteger-cpu-arguments-slope"
  , "lessThanEqualsInteger-memory-arguments"
  , "lessThanInteger-cpu-arguments-intercept"
  , "lessThanInteger-cpu-arguments-slope"
  , "lessThanInteger-memory-arguments"
  , "listData-cpu-arguments"
  , "listData-memory-arguments"
  , "mapData-cpu-arguments"
  , "mapData-memory-arguments"
  , "mkCons-cpu-arguments"
  , "mkCons-memory-arguments"
  , "mkNilData-cpu-arguments"
  , "mkNilData-memory-arguments"
  , "mkNilPairData-cpu-arguments"
  , "mkNilPairData-memory-arguments"
  , "mkPairData-cpu-arguments"
  , "mkPairData-memory-arguments"
  , "modInteger-cpu-arguments-constant"
  , "modInteger-cpu-arguments-model-arguments-intercept"
  , "modInteger-cpu-arguments-model-arguments-slope"
  , "modInteger-memory-arguments-intercept"
  , "modInteger-memory-arguments-minimum"
  , "modInteger-memory-arguments-slope"
  , "multiplyInteger-cpu-arguments-intercept"
  , "multiplyInteger-cpu-arguments-slope"
  , "multiplyInteger-memory-arguments-intercept"
  , "multiplyInteger-memory-arguments-slope"
  , "nullList-cpu-arguments"
  , "nullList-memory-arguments"
  , "quotientInteger-cpu-arguments-constant"
  , "quotientInteger-cpu-arguments-model-arguments-intercept"
  , "quotientInteger-cpu-arguments-model-arguments-slope"
  , "quotientInteger-memory-arguments-intercept"
  , "quotientInteger-memory-arguments-minimum"
  , "quotientInteger-memory-arguments-slope"
  , "remainderInteger-cpu-arguments-constant"
  , "remainderInteger-cpu-arguments-model-arguments-intercept"
  , "remainderInteger-cpu-arguments-model-arguments-slope"
  , "remainderInteger-memory-arguments-intercept"
  , "remainderInteger-memory-arguments-minimum"
  , "remainderInteger-memory-arguments-slope"
  , "sha2_256-cpu-arguments-intercept"
  , "sha2_256-cpu-arguments-slope"
  , "sha2_256-memory-arguments"
  , "sha3_256-cpu-arguments-intercept"
  , "sha3_256-cpu-arguments-slope"
  , "sha3_256-memory-arguments"
  , "sliceByteString-cpu-arguments-intercept"
  , "sliceByteString-cpu-arguments-slope"
  , "sliceByteString-memory-arguments-intercept"
  , "sliceByteString-memory-arguments-slope"
  , "sndPair-cpu-arguments"
  , "sndPair-memory-arguments"
  , "subtractInteger-cpu-arguments-intercept"
  , "subtractInteger-cpu-arguments-slope"
  , "subtractInteger-memory-arguments-intercept"
  , "subtractInteger-memory-arguments-slope"
  , "tailList-cpu-arguments"
  , "tailList-memory-arguments"
  , "trace-cpu-arguments"
  , "trace-memory-arguments"
  , "unBData-cpu-arguments"
  , "unBData-memory-arguments"
  , "unConstrData-cpu-arguments"
  , "unConstrData-memory-arguments"
  , "unIData-cpu-arguments"
  , "unIData-memory-arguments"
  , "unListData-cpu-arguments"
  , "unListData-memory-arguments"
  , "unMapData-cpu-arguments"
  , "unMapData-memory-arguments"
  , "verifySignature-cpu-arguments-intercept"
  , "verifySignature-cpu-arguments-slope"
  , "verifySignature-memory-arguments"
  ]
  ++
  repeat (error "PlutusV1 cost with no name")

plutusV2CostNames :: [String]
plutusV2CostNames =
  [
    "addInteger-cpu-arguments-intercept"
  , "addInteger-cpu-arguments-slope"
  , "addInteger-memory-arguments-intercept"
  , "addInteger-memory-arguments-slope"
  , "appendByteString-cpu-arguments-intercept"
  , "appendByteString-cpu-arguments-slope"
  , "appendByteString-memory-arguments-intercept"
  , "appendByteString-memory-arguments-slope"
  , "appendString-cpu-arguments-intercept"
  , "appendString-cpu-arguments-slope"
  , "appendString-memory-arguments-intercept"
  , "appendString-memory-arguments-slope"
  , "bData-cpu-arguments"
  , "bData-memory-arguments"
  , "blake2b_256-cpu-arguments-intercept"
  , "blake2b_256-cpu-arguments-slope"
  , "blake2b_256-memory-arguments"
  , "cekApplyCost-exBudgetCPU"
  , "cekApplyCost-exBudgetMemory"
  , "cekBuiltinCost-exBudgetCPU"
  , "cekBuiltinCost-exBudgetMemory"
  , "cekConstCost-exBudgetCPU"
  , "cekConstCost-exBudgetMemory"
  , "cekDelayCost-exBudgetCPU"
  , "cekDelayCost-exBudgetMemory"
  , "cekForceCost-exBudgetCPU"
  , "cekForceCost-exBudgetMemory"
  , "cekLamCost-exBudgetCPU"
  , "cekLamCost-exBudgetMemory"
  , "cekStartupCost-exBudgetCPU"
  , "cekStartupCost-exBudgetMemory"
  , "cekVarCost-exBudgetCPU"
  , "cekVarCost-exBudgetMemory"
  , "chooseData-cpu-arguments"
  , "chooseData-memory-arguments"
  , "chooseList-cpu-arguments"
  , "chooseList-memory-arguments"
  , "chooseUnit-cpu-arguments"
  , "chooseUnit-memory-arguments"
  , "consByteString-cpu-arguments-intercept"
  , "consByteString-cpu-arguments-slope"
  , "consByteString-memory-arguments-intercept"
  , "consByteString-memory-arguments-slope"
  , "constrData-cpu-arguments"
  , "constrData-memory-arguments"
  , "decodeUtf8-cpu-arguments-intercept"
  , "decodeUtf8-cpu-arguments-slope"
  , "decodeUtf8-memory-arguments-intercept"
  , "decodeUtf8-memory-arguments-slope"
  , "divideInteger-cpu-arguments-constant"
  , "divideInteger-cpu-arguments-model-arguments-intercept"
  , "divideInteger-cpu-arguments-model-arguments-slope"
  , "divideInteger-memory-arguments-intercept"
  , "divideInteger-memory-arguments-minimum"
  , "divideInteger-memory-arguments-slope"
  , "encodeUtf8-cpu-arguments-intercept"
  , "encodeUtf8-cpu-arguments-slope"
  , "encodeUtf8-memory-arguments-intercept"
  , "encodeUtf8-memory-arguments-slope"
  , "equalsByteString-cpu-arguments-constant"
  , "equalsByteString-cpu-arguments-intercept"
  , "equalsByteString-cpu-arguments-slope"
  , "equalsByteString-memory-arguments"
  , "equalsData-cpu-arguments-intercept"
  , "equalsData-cpu-arguments-slope"
  , "equalsData-memory-arguments"
  , "equalsInteger-cpu-arguments-intercept"
  , "equalsInteger-cpu-arguments-slope"
  , "equalsInteger-memory-arguments"
  , "equalsString-cpu-arguments-constant"
  , "equalsString-cpu-arguments-intercept"
  , "equalsString-cpu-arguments-slope"
  , "equalsString-memory-arguments"
  , "fstPair-cpu-arguments"
  , "fstPair-memory-arguments"
  , "headList-cpu-arguments"
  , "headList-memory-arguments"
  , "iData-cpu-arguments"
  , "iData-memory-arguments"
  , "ifThenElse-cpu-arguments"
  , "ifThenElse-memory-arguments"
  , "indexByteString-cpu-arguments"
  , "indexByteString-memory-arguments"
  , "lengthOfByteString-cpu-arguments"
  , "lengthOfByteString-memory-arguments"
  , "lessThanByteString-cpu-arguments-intercept"
  , "lessThanByteString-cpu-arguments-slope"
  , "lessThanByteString-memory-arguments"
  , "lessThanEqualsByteString-cpu-arguments-intercept"
  , "lessThanEqualsByteString-cpu-arguments-slope"
  , "lessThanEqualsByteString-memory-arguments"
  , "lessThanEqualsInteger-cpu-arguments-intercept"
  , "lessThanEqualsInteger-cpu-arguments-slope"
  , "lessThanEqualsInteger-memory-arguments"
  , "lessThanInteger-cpu-arguments-intercept"
  , "lessThanInteger-cpu-arguments-slope"
  , "lessThanInteger-memory-arguments"
  , "listData-cpu-arguments"
  , "listData-memory-arguments"
  , "mapData-cpu-arguments"
  , "mapData-memory-arguments"
  , "mkCons-cpu-arguments"
  , "mkCons-memory-arguments"
  , "mkNilData-cpu-arguments"
  , "mkNilData-memory-arguments"
  , "mkNilPairData-cpu-arguments"
  , "mkNilPairData-memory-arguments"
  , "mkPairData-cpu-arguments"
  , "mkPairData-memory-arguments"
  , "modInteger-cpu-arguments-constant"
  , "modInteger-cpu-arguments-model-arguments-intercept"
  , "modInteger-cpu-arguments-model-arguments-slope"
  , "modInteger-memory-arguments-intercept"
  , "modInteger-memory-arguments-minimum"
  , "modInteger-memory-arguments-slope"
  , "multiplyInteger-cpu-arguments-intercept"
  , "multiplyInteger-cpu-arguments-slope"
  , "multiplyInteger-memory-arguments-intercept"
  , "multiplyInteger-memory-arguments-slope"
  , "nullList-cpu-arguments"
  , "nullList-memory-arguments"
  , "quotientInteger-cpu-arguments-constant"
  , "quotientInteger-cpu-arguments-model-arguments-intercept"
  , "quotientInteger-cpu-arguments-model-arguments-slope"
  , "quotientInteger-memory-arguments-intercept"
  , "quotientInteger-memory-arguments-minimum"
  , "quotientInteger-memory-arguments-slope"
  , "remainderInteger-cpu-arguments-constant"
  , "remainderInteger-cpu-arguments-model-arguments-intercept"
  , "remainderInteger-cpu-arguments-model-arguments-slope"
  , "remainderInteger-memory-arguments-intercept"
  , "remainderInteger-memory-arguments-minimum"
  , "remainderInteger-memory-arguments-slope"
  , "serialiseData-cpu-arguments-intercept"
  , "serialiseData-cpu-arguments-slope"
  , "serialiseData-memory-arguments-intercept"
  , "serialiseData-memory-arguments-slope"
  , "sha2_256-cpu-arguments-intercept"
  , "sha2_256-cpu-arguments-slope"
  , "sha2_256-memory-arguments"
  , "sha3_256-cpu-arguments-intercept"
  , "sha3_256-cpu-arguments-slope"
  , "sha3_256-memory-arguments"
  , "sliceByteString-cpu-arguments-intercept"
  , "sliceByteString-cpu-arguments-slope"
  , "sliceByteString-memory-arguments-intercept"
  , "sliceByteString-memory-arguments-slope"
  , "sndPair-cpu-arguments"
  , "sndPair-memory-arguments"
  , "subtractInteger-cpu-arguments-intercept"
  , "subtractInteger-cpu-arguments-slope"
  , "subtractInteger-memory-arguments-intercept"
  , "subtractInteger-memory-arguments-slope"
  , "tailList-cpu-arguments"
  , "tailList-memory-arguments"
  , "trace-cpu-arguments"
  , "trace-memory-arguments"
  , "unBData-cpu-arguments"
  , "unBData-memory-arguments"
  , "unConstrData-cpu-arguments"
  , "unConstrData-memory-arguments"
  , "unIData-cpu-arguments"
  , "unIData-memory-arguments"
  , "unListData-cpu-arguments"
  , "unListData-memory-arguments"
  , "unMapData-cpu-arguments"
  , "unMapData-memory-arguments"
  , "verifyEcdsaSecp256k1Signature-cpu-arguments"
  , "verifyEcdsaSecp256k1Signature-memory-arguments"
  , "verifyEd25519Signature-cpu-arguments-intercept"
  , "verifyEd25519Signature-cpu-arguments-slope"
  , "verifyEd25519Signature-memory-arguments"
  , "verifySchnorrSecp256k1Signature-cpu-arguments-intercept"
  , "verifySchnorrSecp256k1Signature-cpu-arguments-slope"
  , "verifySchnorrSecp256k1Signature-memory-arguments"
  ]
  ++
  repeat (error "PlutusV2 cost with no name")

-- https://github.com/IntersectMBO/plutus/blob/3400c4ca44f86b1c3ee135ceb6353b659109172c/plutus-ledger-api/CostModel/Params/CostModelParams/costModelParamNames.txt.golden#L242
plutusV3CostNames :: [String]
plutusV3CostNames =
  [
    "addInteger-cpu-arguments-intercept"
  , "addInteger-cpu-arguments-slope"
  , "addInteger-memory-arguments-intercept"
  , "addInteger-memory-arguments-slope"
  , "appendByteString-cpu-arguments-intercept"
  , "appendByteString-cpu-arguments-slope"
  , "appendByteString-memory-arguments-intercept"
  , "appendByteString-memory-arguments-slope"
  , "appendString-cpu-arguments-intercept"
  , "appendString-cpu-arguments-slope"
  , "appendString-memory-arguments-intercept"
  , "appendString-memory-arguments-slope"
  , "bData-cpu-arguments"
  , "bData-memory-arguments"
  , "blake2b_256-cpu-arguments-intercept"
  , "blake2b_256-cpu-arguments-slope"
  , "blake2b_256-memory-arguments"
  , "cekApplyCost-exBudgetCPU"
  , "cekApplyCost-exBudgetMemory"
  , "cekBuiltinCost-exBudgetCPU"
  , "cekBuiltinCost-exBudgetMemory"
  , "cekConstCost-exBudgetCPU"
  , "cekConstCost-exBudgetMemory"
  , "cekDelayCost-exBudgetCPU"
  , "cekDelayCost-exBudgetMemory"
  , "cekForceCost-exBudgetCPU"
  , "cekForceCost-exBudgetMemory"
  , "cekLamCost-exBudgetCPU"
  , "cekLamCost-exBudgetMemory"
  , "cekStartupCost-exBudgetCPU"
  , "cekStartupCost-exBudgetMemory"
  , "cekVarCost-exBudgetCPU"
  , "cekVarCost-exBudgetMemory"
  , "chooseData-cpu-arguments"
  , "chooseData-memory-arguments"
  , "chooseList-cpu-arguments"
  , "chooseList-memory-arguments"
  , "chooseUnit-cpu-arguments"
  , "chooseUnit-memory-arguments"
  , "consByteString-cpu-arguments-intercept"
  , "consByteString-cpu-arguments-slope"
  , "consByteString-memory-arguments-intercept"
  , "consByteString-memory-arguments-slope"
  , "constrData-cpu-arguments"
  , "constrData-memory-arguments"
  , "decodeUtf8-cpu-arguments-intercept"
  , "decodeUtf8-cpu-arguments-slope"
  , "decodeUtf8-memory-arguments-intercept"
  , "decodeUtf8-memory-arguments-slope"
  , "divideInteger-cpu-arguments-constant"
  , "divideInteger-cpu-arguments-model-arguments-c00"
  , "divideInteger-cpu-arguments-model-arguments-c01"
  , "divideInteger-cpu-arguments-model-arguments-c02"
  , "divideInteger-cpu-arguments-model-arguments-c10"
  , "divideInteger-cpu-arguments-model-arguments-c11"
  , "divideInteger-cpu-arguments-model-arguments-c20"
  , "divideInteger-cpu-arguments-model-arguments-minimum"
  , "divideInteger-memory-arguments-intercept"
  , "divideInteger-memory-arguments-minimum"
  , "divideInteger-memory-arguments-slope"
  , "encodeUtf8-cpu-arguments-intercept"
  , "encodeUtf8-cpu-arguments-slope"
  , "encodeUtf8-memory-arguments-intercept"
  , "encodeUtf8-memory-arguments-slope"
  , "equalsByteString-cpu-arguments-constant"
  , "equalsByteString-cpu-arguments-intercept"
  , "equalsByteString-cpu-arguments-slope"
  , "equalsByteString-memory-arguments"
  , "equalsData-cpu-arguments-intercept"
  , "equalsData-cpu-arguments-slope"
  , "equalsData-memory-arguments"
  , "equalsInteger-cpu-arguments-intercept"
  , "equalsInteger-cpu-arguments-slope"
  , "equalsInteger-memory-arguments"
  , "equalsString-cpu-arguments-constant"
  , "equalsString-cpu-arguments-intercept"
  , "equalsString-cpu-arguments-slope"
  , "equalsString-memory-arguments"
  , "fstPair-cpu-arguments"
  , "fstPair-memory-arguments"
  , "headList-cpu-arguments"
  , "headList-memory-arguments"
  , "iData-cpu-arguments"
  , "iData-memory-arguments"
  , "ifThenElse-cpu-arguments"
  , "ifThenElse-memory-arguments"
  , "indexByteString-cpu-arguments"
  , "indexByteString-memory-arguments"
  , "lengthOfByteString-cpu-arguments"
  , "lengthOfByteString-memory-arguments"
  , "lessThanByteString-cpu-arguments-intercept"
  , "lessThanByteString-cpu-arguments-slope"
  , "lessThanByteString-memory-arguments"
  , "lessThanEqualsByteString-cpu-arguments-intercept"
  , "lessThanEqualsByteString-cpu-arguments-slope"
  , "lessThanEqualsByteString-memory-arguments"
  , "lessThanEqualsInteger-cpu-arguments-intercept"
  , "lessThanEqualsInteger-cpu-arguments-slope"
  , "lessThanEqualsInteger-memory-arguments"
  , "lessThanInteger-cpu-arguments-intercept"
  , "lessThanInteger-cpu-arguments-slope"
  , "lessThanInteger-memory-arguments"
  , "listData-cpu-arguments"
  , "listData-memory-arguments"
  , "mapData-cpu-arguments"
  , "mapData-memory-arguments"
  , "mkCons-cpu-arguments"
  , "mkCons-memory-arguments"
  , "mkNilData-cpu-arguments"
  , "mkNilData-memory-arguments"
  , "mkNilPairData-cpu-arguments"
  , "mkNilPairData-memory-arguments"
  , "mkPairData-cpu-arguments"
  , "mkPairData-memory-arguments"
  , "modInteger-cpu-arguments-constant"
  , "modInteger-cpu-arguments-model-arguments-c00"
  , "modInteger-cpu-arguments-model-arguments-c01"
  , "modInteger-cpu-arguments-model-arguments-c02"
  , "modInteger-cpu-arguments-model-arguments-c10"
  , "modInteger-cpu-arguments-model-arguments-c11"
  , "modInteger-cpu-arguments-model-arguments-c20"
  , "modInteger-cpu-arguments-model-arguments-minimum"
  , "modInteger-memory-arguments-intercept"
  , "modInteger-memory-arguments-slope"
  , "multiplyInteger-cpu-arguments-intercept"
  , "multiplyInteger-cpu-arguments-slope"
  , "multiplyInteger-memory-arguments-intercept"
  , "multiplyInteger-memory-arguments-slope"
  , "nullList-cpu-arguments"
  , "nullList-memory-arguments"
  , "quotientInteger-cpu-arguments-constant"
  , "quotientInteger-cpu-arguments-model-arguments-c00"
  , "quotientInteger-cpu-arguments-model-arguments-c01"
  , "quotientInteger-cpu-arguments-model-arguments-c02"
  , "quotientInteger-cpu-arguments-model-arguments-c10"
  , "quotientInteger-cpu-arguments-model-arguments-c11"
  , "quotientInteger-cpu-arguments-model-arguments-c20"
  , "quotientInteger-cpu-arguments-model-arguments-minimum"
  , "quotientInteger-memory-arguments-intercept"
  , "quotientInteger-memory-arguments-minimum"
  , "quotientInteger-memory-arguments-slope"
  , "remainderInteger-cpu-arguments-constant"
  , "remainderInteger-cpu-arguments-model-arguments-c00"
  , "remainderInteger-cpu-arguments-model-arguments-c01"
  , "remainderInteger-cpu-arguments-model-arguments-c02"
  , "remainderInteger-cpu-arguments-model-arguments-c10"
  , "remainderInteger-cpu-arguments-model-arguments-c11"
  , "remainderInteger-cpu-arguments-model-arguments-c20"
  , "remainderInteger-cpu-arguments-model-arguments-minimum"
  , "remainderInteger-memory-arguments-intercept"
  , "remainderInteger-memory-arguments-slope"
  , "serialiseData-cpu-arguments-intercept"
  , "serialiseData-cpu-arguments-slope"
  , "serialiseData-memory-arguments-intercept"
  , "serialiseData-memory-arguments-slope"
  , "sha2_256-cpu-arguments-intercept"
  , "sha2_256-cpu-arguments-slope"
  , "sha2_256-memory-arguments"
  , "sha3_256-cpu-arguments-intercept"
  , "sha3_256-cpu-arguments-slope"
  , "sha3_256-memory-arguments"
  , "sliceByteString-cpu-arguments-intercept"
  , "sliceByteString-cpu-arguments-slope"
  , "sliceByteString-memory-arguments-intercept"
  , "sliceByteString-memory-arguments-slope"
  , "sndPair-cpu-arguments"
  , "sndPair-memory-arguments"
  , "subtractInteger-cpu-arguments-intercept"
  , "subtractInteger-cpu-arguments-slope"
  , "subtractInteger-memory-arguments-intercept"
  , "subtractInteger-memory-arguments-slope"
  , "tailList-cpu-arguments"
  , "tailList-memory-arguments"
  , "trace-cpu-arguments"
  , "trace-memory-arguments"
  , "unBData-cpu-arguments"
  , "unBData-memory-arguments"
  , "unConstrData-cpu-arguments"
  , "unConstrData-memory-arguments"
  , "unIData-cpu-arguments"
  , "unIData-memory-arguments"
  , "unListData-cpu-arguments"
  , "unListData-memory-arguments"
  , "unMapData-cpu-arguments"
  , "unMapData-memory-arguments"
  , "verifyEcdsaSecp256k1Signature-cpu-arguments"
  , "verifyEcdsaSecp256k1Signature-memory-arguments"
  , "verifyEd25519Signature-cpu-arguments-intercept"
  , "verifyEd25519Signature-cpu-arguments-slope"
  , "verifyEd25519Signature-memory-arguments"
  , "verifySchnorrSecp256k1Signature-cpu-arguments-intercept"
  , "verifySchnorrSecp256k1Signature-cpu-arguments-slope"
  , "verifySchnorrSecp256k1Signature-memory-arguments"
  , "cekConstrCost-exBudgetCPU"
  , "cekConstrCost-exBudgetMemory"
  , "cekCaseCost-exBudgetCPU"
  , "cekCaseCost-exBudgetMemory"
  , "bls12_381_G1_add-cpu-arguments"
  , "bls12_381_G1_add-memory-arguments"
  , "bls12_381_G1_compress-cpu-arguments"
  , "bls12_381_G1_compress-memory-arguments"
  , "bls12_381_G1_equal-cpu-arguments"
  , "bls12_381_G1_equal-memory-arguments"
  , "bls12_381_G1_hashToGroup-cpu-arguments-intercept"
  , "bls12_381_G1_hashToGroup-cpu-arguments-slope"
  , "bls12_381_G1_hashToGroup-memory-arguments"
  , "bls12_381_G1_neg-cpu-arguments"
  , "bls12_381_G1_neg-memory-arguments"
  , "bls12_381_G1_scalarMul-cpu-arguments-intercept"
  , "bls12_381_G1_scalarMul-cpu-arguments-slope"
  , "bls12_381_G1_scalarMul-memory-arguments"
  , "bls12_381_G1_uncompress-cpu-arguments"
  , "bls12_381_G1_uncompress-memory-arguments"
  , "bls12_381_G2_add-cpu-arguments"
  , "bls12_381_G2_add-memory-arguments"
  , "bls12_381_G2_compress-cpu-arguments"
  , "bls12_381_G2_compress-memory-arguments"
  , "bls12_381_G2_equal-cpu-arguments"
  , "bls12_381_G2_equal-memory-arguments"
  , "bls12_381_G2_hashToGroup-cpu-arguments-intercept"
  , "bls12_381_G2_hashToGroup-cpu-arguments-slope"
  , "bls12_381_G2_hashToGroup-memory-arguments"
  , "bls12_381_G2_neg-cpu-arguments"
  , "bls12_381_G2_neg-memory-arguments"
  , "bls12_381_G2_scalarMul-cpu-arguments-intercept"
  , "bls12_381_G2_scalarMul-cpu-arguments-slope"
  , "bls12_381_G2_scalarMul-memory-arguments"
  , "bls12_381_G2_uncompress-cpu-arguments"
  , "bls12_381_G2_uncompress-memory-arguments"
  , "bls12_381_finalVerify-cpu-arguments"
  , "bls12_381_finalVerify-memory-arguments"
  , "bls12_381_millerLoop-cpu-arguments"
  , "bls12_381_millerLoop-memory-arguments"
  , "bls12_381_mulMlResult-cpu-arguments"
  , "bls12_381_mulMlResult-memory-arguments"
  , "keccak_256-cpu-arguments-intercept"
  , "keccak_256-cpu-arguments-slope"
  , "keccak_256-memory-arguments"
  , "blake2b_224-cpu-arguments-intercept"
  , "blake2b_224-cpu-arguments-slope"
  , "blake2b_224-memory-arguments"
  , "integerToByteString-cpu-arguments-c0"
  , "integerToByteString-cpu-arguments-c1"
  , "integerToByteString-cpu-arguments-c2"
  , "integerToByteString-memory-arguments-intercept"
  , "integerToByteString-memory-arguments-slope"
  , "byteStringToInteger-cpu-arguments-c0"
  , "byteStringToInteger-cpu-arguments-c1"
  , "byteStringToInteger-cpu-arguments-c2"
  , "byteStringToInteger-memory-arguments-intercept"
  , "byteStringToInteger-memory-arguments-slope"
  , "andByteString-cpu-arguments-intercept"
  , "andByteString-cpu-arguments-slope1"
  , "andByteString-cpu-arguments-slope2"
  , "andByteString-memory-arguments-intercept"
  , "andByteString-memory-arguments-slope"
  , "orByteString-cpu-arguments-intercept"
  , "orByteString-cpu-arguments-slope1"
  , "orByteString-cpu-arguments-slope2"
  , "orByteString-memory-arguments-intercept"
  , "orByteString-memory-arguments-slope"
  , "xorByteString-cpu-arguments-intercept"
  , "xorByteString-cpu-arguments-slope1"
  , "xorByteString-cpu-arguments-slope2"
  , "xorByteString-memory-arguments-intercept"
  , "xorByteString-memory-arguments-slope"
  , "complementByteString-cpu-arguments-intercept"
  , "complementByteString-cpu-arguments-slope"
  , "complementByteString-memory-arguments-intercept"
  , "complementByteString-memory-arguments-slope"
  , "readBit-cpu-arguments"
  , "readBit-memory-arguments"
  , "writeBits-cpu-arguments-intercept"
  , "writeBits-cpu-arguments-slope"
  , "writeBits-memory-arguments-intercept"
  , "writeBits-memory-arguments-slope"
  , "replicateByte-cpu-arguments-intercept"
  , "replicateByte-cpu-arguments-slope"
  , "replicateByte-memory-arguments-intercept"
  , "replicateByte-memory-arguments-slope"
  , "shiftByteString-cpu-arguments-intercept"
  , "shiftByteString-cpu-arguments-slope"
  , "shiftByteString-memory-arguments-intercept"
  , "shiftByteString-memory-arguments-slope"
  , "rotateByteString-cpu-arguments-intercept"
  , "rotateByteString-cpu-arguments-slope"
  , "rotateByteString-memory-arguments-intercept"
  , "rotateByteString-memory-arguments-slope"
  , "countSetBits-cpu-arguments-intercept"
  , "countSetBits-cpu-arguments-slope"
  , "countSetBits-memory-arguments"
  , "findFirstSetBit-cpu-arguments-intercept"
  , "findFirstSetBit-cpu-arguments-slope"
  , "findFirstSetBit-memory-arguments"
  , "ripemd_160-cpu-arguments-intercept"
  , "ripemd_160-cpu-arguments-slope"
  , "ripemd_160-memory-arguments"
  ]
  ++
  map (("PlutusV3_Unknown_" ++) . show) ([1,2..]::[Int])
